View Javadoc
1 /* 2 * Scope: a generic MVC framework. 3 * Copyright (c) 2000-2002, The Scope team 4 * All rights reserved. 5 * 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions 9 * are met: 10 * 11 * Redistributions of source code must retain the above copyright 12 * notice, this list of conditions and the following disclaimer. 13 * 14 * Redistributions in binary form must reproduce the above copyright 15 * notice, this list of conditions and the following disclaimer in the 16 * documentation and/or other materials provided with the distribution. 17 * 18 * Neither the name "Scope" nor the names of its contributors 19 * may be used to endorse or promote products derived from this software 20 * without specific prior written permission. 21 * 22 * 23 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 24 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 25 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 26 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR 27 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 28 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 29 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 30 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 31 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 32 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 33 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 34 * 35 * 36 * $Id: SComboBox.java,v 1.13 2002/09/13 17:04:39 ludovicc Exp $ 37 */ 38 package org.scopemvc.view.swing; 39 40 41 import java.awt.event.ActionEvent; 42 import java.awt.event.ActionListener; 43 import java.beans.Beans; 44 import javax.swing.ComboBoxEditor; 45 import javax.swing.ComboBoxModel; 46 import javax.swing.JComboBox; 47 import javax.swing.JToolTip; 48 import javax.swing.ListCellRenderer; 49 import org.apache.commons.logging.Log; 50 import org.apache.commons.logging.LogFactory; 51 import org.scopemvc.core.Control; 52 import org.scopemvc.core.Controller; 53 import org.scopemvc.core.Selector; 54 import org.scopemvc.core.View; 55 import org.scopemvc.util.convertor.StringConvertor; 56 57 /*** 58 * <P> 59 * 60 * A JComboBox that uses a {@link SComboBoxModel} to bind to model properties 61 * for the list of items and to bind the selected item to a property. Uses a 62 * {@link SListCellRenderer} to draw items in the list. Uses a {@link 63 * SComboBoxEditor} if editable. </P> <P> 64 * 65 * SComboBox can issue Controls on selection changes. </P> <P> 66 * 67 * SList doesn't itself bind to a model: it delegates all binding to its 68 * SComboBoxModel. </P> <P> 69 * 70 * Examples for SComboBox use can be found in <code>samples.swing.combodemo</code> 71 * package, and see {@link SComboBoxModel} and {@link SAbstractListModel}. </P> 72 * <p> 73 * 74 * Elements (rows) in the data model can be arbitrary class (e.g. Person, 75 * Employee etc.). Scope's combobox renderer can have set Selector for desired 76 * element attribute (e.g. "name"). If selector is ommited, then toString() 77 * value is drawn. If elements are of types for which exist StringConvertor, the 78 * combo box can be editable (exactly not the elements, but selected item 79 * property, however it has make sense to have elements and selected item of the 80 * same type.) </p> <p> 81 * 82 * <i>Data model</i> will be typically array (<code>Object[]</code>) or list 83 * derived from <code>java.util.List</code>. For this case there is no need to 84 * set size model. For example: <pre> 85 * class SelectedPerson { 86 * ... 87 * public void setSelectedPerson(Person p) {...} 88 * public Person getSelectedPerson() {...} 89 * } 90 * ... 91 * List persons = getSomePersons(); 92 * combo.setDataModel(persons); 93 * combo.setSelectionSelectorString("selectedPerson"); // a property of the bound view model 94 * </pre> </p> <p> 95 * 96 * Some times data elements of combobox changes during combobox life cycle. For 97 * this case is better to use single model for both selection and element list. 98 * The list is treated as model property and can be changed: <pre> 99 * class PersonSelection extends BasicModel { 100 * public final static Selector PERSONS = Selector.fromString("persons"); 101 * ... 102 * public void setSelectedPerson(Person p) {...} 103 * public Person getSelectedPerson() {...} 104 * public List getPersons() {...} 105 * 106 * ... 107 * // in some method 108 * persons = fetchOtherPersons(); 109 * super.fireModelChange(ModelChangeEvent.VALUE_CHANGED, PERSONS); 110 * // now are data in combobox refreshed 111 * ... 112 * } 113 * ... 114 * SComboBox combo = new SComboBox(); 115 * combo.setSelector(PERSONS); 116 * combo.setSelectionSelectorString("selectedPerson"); 117 * ... 118 * </pre> Note that since <i>persons</i> attribute is of type <code>java.util.List</code> 119 * , there is again no need to set size selector. </p> <p> 120 * 121 * In the last variation of the example is shown, where the size model and 122 * selector is need. Java Beans specifiaction says, that indexed properties can 123 * be exposed as a single array value. However, this is not requirement. Let's 124 * see example: <pre> 125 * class Persons { 126 * ... 127 * public Person getPerson(int i) {...} 128 * public void setPerson(int i, Person p) {...} 129 * 130 * public int getPersonsNumber() {...} 131 * } 132 * ... 133 * SComboBox combo = new SComboBox(); 134 * combo.setSelectorString("person"); 135 * combo.setSizeSelectorString("personsNumber"); 136 * ... 137 * </pre> </p> 138 * 139 * @author <A HREF="mailto:daniel.michalik@autel.cz">Daniel Michalik</A> 140 * @author <A HREF="mailto:smeyfroi@users.sourceforge.net">Steve Meyfroidt</A> 141 * @created 05 September 2002 142 * @version $Revision: 1.13 $ $Date: 2002/09/13 17:04:39 $ 143 * @see SComboBoxModel 144 * @see SAbstractListModel 145 * @see SList 146 */ 147 public class SComboBox extends JComboBox 148 implements View, Refreshable { 149 150 private static final Log LOG = LogFactory.getLog(SComboBox.class); 151 152 // -------------------- Controls ----------------------- 153 154 private String selectionControlID; 155 156 // ------------- Support validation failures from selection ------------- 157 158 /*** 159 * Helper to manage validation state. 160 */ 161 private ValidationHelper validationHelper = new ValidationHelper(this); 162 163 164 /*** 165 * Constructor for the SComboBox object 166 */ 167 public SComboBox() { 168 setRenderer(new SListCellRenderer()); 169 setEditor(new SComboBoxEditor()); 170 setModel(new SComboBoxModel(this)); 171 addActionListener( 172 new ActionListener() { 173 public void actionPerformed(ActionEvent inEvent) { 174 issueChangeSelectionControl(); 175 } 176 }); 177 setEnabled(Beans.isDesignTime()); 178 updateUI(); 179 } 180 181 182 // ---------- Implement View by delegation to SListModel and SListSelectionModel ---------- 183 184 /*** 185 * Gets the bound model 186 * 187 * @return The boundModel value 188 */ 189 public final Object getBoundModel() { 190 return ((SComboBoxModel) getModel()).getBoundModel(); 191 } 192 193 194 /*** 195 * Gets the selector 196 * 197 * @return The selector value 198 */ 199 public final Selector getSelector() { 200 return ((SComboBoxModel) getModel()).getSelector(); 201 } 202 203 204 /*** 205 * Gets the selection selector 206 * 207 * @return The selectionSelector value 208 */ 209 public final Selector getSelectionSelector() { 210 return ((SComboBoxModel) getModel()).getSelectionSelector(); 211 } 212 213 214 /*** 215 * Gets the renderer selector 216 * 217 * @return The rendererSelector value 218 */ 219 public final Selector getRendererSelector() { 220 ListCellRenderer renderer = getRenderer(); 221 if (!(renderer instanceof SListCellRenderer)) { 222 return null; 223 } 224 return ((SListCellRenderer) renderer).getTextSelector(); 225 } 226 227 228 /*** 229 * Gets the renderer icon selector 230 * 231 * @return The rendererIconSelector value 232 */ 233 public final Selector getRendererIconSelector() { 234 ListCellRenderer renderer = getRenderer(); 235 if (!(renderer instanceof SListCellRenderer)) { 236 return null; 237 } 238 return ((SListCellRenderer) renderer).getIconSelector(); 239 } 240 241 242 /*** 243 * Gets the size selector 244 * 245 * @return The sizeSelector value 246 */ 247 public final Selector getSizeSelector() { 248 return ((SComboBoxModel) getModel()).getSizeSelector(); 249 } 250 251 /*** 252 * Gets the change selection control ID 253 * 254 * @return The changeSelectionControlID value 255 */ 256 public final String getChangeSelectionControlID() { 257 return selectionControlID; 258 } 259 260 261 /*** 262 * TODO: document the method 263 */ 264 public void issueChangeSelectionControl() { 265 if (selectionControlID != null) { 266 Control control = new Control(selectionControlID); 267 issueControl(control); 268 } 269 } 270 271 272 /*** 273 * Don't assign a direct Controller to ComboBox, instead delegate to the 274 * containing SwingView that has a parent Controller. 275 * 276 * @return The controller value 277 */ 278 public Controller getController() { 279 return null; 280 } 281 282 283 /*** 284 * Don't assign a direct Controller to ComboBox, instead delegate to the 285 * containing SwingView that has a parent Controller. 286 * 287 * @param inControl TODO: Describe the Parameter 288 */ 289 public void issueControl(Control inControl) { 290 SwingUtil.issueControl(this, inControl); 291 } 292 293 294 /*** 295 * Sets the bound model 296 * 297 * @param inModel The new boundModel value 298 */ 299 public final void setBoundModel(Object inModel) { 300 ((SComboBoxModel) getModel()).setBoundModel(inModel); 301 } 302 303 /*** 304 * Set the Selector for the list data. Should be a java.util.List or an 305 * Object[] or have a "size" property and properties accessible by an 306 * IntIndexedSelector. 307 * 308 * @param inSelector The new selector value 309 */ 310 public final void setSelector(Selector inSelector) { 311 ((SComboBoxModel) getModel()).setSelector(inSelector); 312 } 313 314 315 /*** 316 * Set the Selector for the list data. Should be a java.util.List or an 317 * Object[] or have a "size" property and properties accessible by an 318 * IntIndexedSelector. 319 * 320 * @param inSelectorString The new selectorString value 321 */ 322 public final void setSelectorString(String inSelectorString) { 323 ((SComboBoxModel) getModel()).setSelectorString(inSelectorString); 324 } 325 326 /*** 327 * Set the Selector for the list selection: this property will be bound to 328 * the list's single selection. 329 * 330 * @param inSelector The new selectionSelector value 331 */ 332 public final void setSelectionSelector(Selector inSelector) { 333 ((SComboBoxModel) getModel()).setSelectionSelector(inSelector); 334 } 335 336 337 /*** 338 * Set the Selector for the list selection: this property will be bound to 339 * the list's single selection. 340 * 341 * @param inSelectorString The new selectionSelectorString value 342 */ 343 public final void setSelectionSelectorString(String inSelectorString) { 344 ((SComboBoxModel) getModel()).setSelectionSelectorString(inSelectorString); 345 } 346 347 /*** 348 * Set the Selector for the list cell renderer: this is the property that 349 * will be shown in a list cell (converted to a String). 350 * 351 * @param inSelector The new rendererSelector value 352 */ 353 public final void setRendererSelector(Selector inSelector) { 354 ListCellRenderer renderer = getRenderer(); 355 if (!(renderer instanceof SListCellRenderer)) { 356 throw new UnsupportedOperationException("Not using a Scope bound SListCellRenderer so can't set a Selector on it"); 357 } 358 ((SListCellRenderer) renderer).setTextSelector(inSelector); 359 } 360 361 /*** 362 * Set the Selector for the list cell renderer to get an Icon: this is the 363 * property that will be shown as an Icon in a list cell. 364 * 365 * @param inSelector The new rendererIconSelector value 366 */ 367 public final void setRendererIconSelector(Selector inSelector) { 368 ListCellRenderer renderer = getRenderer(); 369 if (!(renderer instanceof SListCellRenderer)) { 370 throw new UnsupportedOperationException("Not using a Scope bound SListCellRenderer so can't set a Selector on it"); 371 } 372 ((SListCellRenderer) renderer).setIconSelector(inSelector); 373 } 374 375 376 /*** 377 * Set the Selector for the list cell renderer: this is the property that 378 * will be shown in a list cell (converted to a String). 379 * 380 * @param inSelectorString The new rendererSelectorString value 381 */ 382 public final void setRendererSelectorString(String inSelectorString) { 383 ListCellRenderer renderer = getRenderer(); 384 if (!(renderer instanceof SListCellRenderer)) { 385 throw new UnsupportedOperationException("Not using a Scope bound SListCellRenderer so can't set a Selector on it"); 386 } 387 ((SListCellRenderer) renderer).setTextSelectorString(inSelectorString); 388 } 389 390 391 /*** 392 * Set the Selector for the list cell renderer to get an Icon: this is the 393 * property that will be shown as an Icon in a list cell. 394 * 395 * @param inSelectorString The new rendererIconSelectorString value 396 */ 397 public final void setRendererIconSelectorString(String inSelectorString) { 398 ListCellRenderer renderer = getRenderer(); 399 if (!(renderer instanceof SListCellRenderer)) { 400 throw new UnsupportedOperationException("Not using a Scope bound SListCellRenderer so can't set a Selector on it"); 401 } 402 ((SListCellRenderer) renderer).setIconSelectorString(inSelectorString); 403 } 404 405 /*** 406 * Optional: set the Selector for the property that is the size of the items 407 * list. Not needed for lists that are of type Object[] or java.util.List. 408 * 409 * @param inSelector The new sizeSelector value 410 */ 411 public final void setSizeSelector(Selector inSelector) { 412 ((SComboBoxModel) getModel()).setSizeSelector(inSelector); 413 } 414 415 416 /*** 417 * Optional: set the Selector for the property that is the size of the items 418 * list. Not needed for lists that are of type Object[] or java.util.List. 419 * 420 * @param inSelectorString The new sizeSelectorString value 421 */ 422 public final void setSizeSelectorString(String inSelectorString) { 423 ((SComboBoxModel) getModel()).setSizeSelectorString(inSelectorString); 424 } 425 426 /*** 427 * Set the Control ID for the Control that will be issued when the selection 428 * is changed. If null no Control will be issued. 429 * 430 * @param inControlID The new changeSelectionControlID value 431 */ 432 public final void setChangeSelectionControlID(String inControlID) { 433 selectionControlID = inControlID; 434 } 435 436 437 /*** 438 * Force use of this StringConvertor instead of automatically finding one to 439 * match the datatype being edited. 440 * 441 * @param inConvertor The new stringConvertor value 442 */ 443 public void setStringConvertor(StringConvertor inConvertor) { 444 ComboBoxEditor editor = (SComboBoxEditor) getEditor(); 445 if (editor instanceof SComboBoxEditor) { 446 ((SComboBoxEditor) editor).setStringConvertor(inConvertor); 447 } 448 } 449 450 451 /*** 452 * This method is overriden to fix JDK 1.2.x,1.3.x bug: after setting model 453 * combobox sets element 0 as selected. This is violation of MVC paradigm - 454 * model describes some state and should not be modified by view. JDK 1.4 455 * beta has this bug fixed. <p> 456 * 457 * Model should be instance of SComboBoxModel to fix take effect</p> . 458 * 459 * @param m The new model value 460 * @see SComboBoxModel#setSelectedItem(Object) 461 */ 462 public void setModel(ComboBoxModel m) { 463 if (m instanceof SComboBoxModel) { 464 ((SComboBoxModel) m).jdk1_3fixIgnoreSetSelectedItem(true); 465 super.setModel(m); 466 ((SComboBoxModel) m).jdk1_3fixIgnoreSetSelectedItem(false); 467 } else { 468 super.setModel(m); 469 } 470 } 471 472 473 // --------- Set up list binding by delegation ------------- 474 475 /*** 476 * Can use this to specify a static list model for the contents of the list 477 * rather than binding to a dynamic property of some view model. 478 * 479 * @param inModel The new listModel value 480 * @see org.scopemvc.model.collection.ListModelAdaptor 481 */ 482 public void setListModel(Object inModel) { 483 ((SComboBoxModel) getModel()).setListModel(inModel); 484 } 485 486 /*** 487 * Don't assign a Controller to this component, instead delegate to the 488 * containing SwingView that has a parent Controller. 489 * 490 * @param inController The new controller value 491 */ 492 public void setController(Controller inController) { 493 throw new UnsupportedOperationException("Can't assign a Controller to a " + getClass()); 494 } 495 496 // ------------------ Refreshable ------------------------- 497 498 /*** 499 * TODO: document the method 500 */ 501 public void refresh() { 502 ((SComboBoxModel) getModel()).refresh(); 503 } 504 505 506 /*** 507 * TODO: document the method 508 * 509 * @param inException TODO: Describe the Parameter 510 */ 511 public void validationFailed(Exception inException) { 512 validationHelper.validationFailed(inException); 513 } 514 515 516 /*** 517 * TODO: document the method 518 */ 519 public void validationSuccess() { 520 validationHelper.validationSuccess(); 521 } 522 523 524 /*** 525 * TODO: document the method 526 * 527 * @return TODO: Describe the Return Value 528 */ 529 public JToolTip createToolTip() { 530 return validationHelper.createToolTip(super.createToolTip()); 531 } 532 533 }

This page was automatically generated by Maven